package cn.echo.consul.manager.service.impl;

import cn.echo.consul.manager.encrypt.BCrypt;
import cn.echo.consul.manager.entity.Token;
import cn.echo.consul.manager.entity.UserInfo;
import cn.echo.consul.manager.entity.UserPayload;
import cn.echo.consul.manager.exception.BizServiceException;
import cn.echo.consul.manager.repository.ManagerRepository;
import cn.echo.consul.manager.service.AccessTokenService;
import cn.echo.consul.manager.service.UserInfoService;
import cn.echo.consul.manager.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

import static cn.echo.consul.manager.response.ResultCode.*;

/**
 * 用户服务实现类
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {

    final ManagerRepository managerRepository;
    final AccessTokenService accessTokenService;

    final String userKeyPrefix = "manager/user/";

    /**
     * 用户登录
     */
    public Token login(String userId, String secret, String fingerprint) {
        if (StringUtils.isEmpty(userId)) {
            //用户ID不能空
            throw new BizServiceException(F11607);
        }
        if (StringUtils.isEmpty(secret)) {
            //密码不能空
            throw new BizServiceException(F11606);
        }
        UserInfo userInfo = this.getUserInfo(userId);
        //用户不存在
        if (userInfo==null || StringUtils.isEmpty(userInfo.getUserId()) || !userInfo.getUsable()) {
            throw new BizServiceException(F11612);
        }
        //if(!userInfo.getUsable()) {
        //    throw new BizServiceException(F11611);
        //}
        //密码登录判断密码是否正确
        if (!BCrypt.checkpw(secret, userInfo.getSecret())) {
            throw new BizServiceException(F11612);
        }
        UserPayload payload = new UserPayload(userInfo.getUserId(), userInfo.getUserName(), userInfo.getIsAdmin(), fingerprint);
        Token token = accessTokenService.genToken(payload);
        return token;
    }

    /**
     * 用户注册
     */
    public void register(String userId, String userName, String secret, Boolean isAdmin, String creatorId) {
        if (StringUtils.isEmpty(userId) || !StringUtil.isCode(userId)) {
            //用户ID格式错误
            throw new BizServiceException(F11607);
        }
        if (StringUtils.isEmpty(secret) || !StringUtil.isSecret(secret)) {
            //密码格式错误
            throw new BizServiceException(F11606);
        }
        UserInfo userInfo = this.getUserInfo(userId);
        //用户已存在
        if (userInfo!=null) {
            throw new BizServiceException(F11613);
        }
        userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setUsable(true);
        userInfo.setUserName(StringUtils.isEmpty(userName)? userId: userName);
        userInfo.setIsAdmin(isAdmin);
        userInfo.setSecret(BCrypt.hashpw(secret, BCrypt.gensalt()));
        userInfo.setCreatorId(creatorId);
        userInfo.setCreatedDate(new Date());

        managerRepository.update(userKeyPrefix + userId, userInfo);
    }

    /**
     * 修改用户信息
     */
    public void modify(String userId, String userName, Boolean isAdmin, Boolean usable, String updaterId) {
        if (StringUtils.isEmpty(userId)) {
            //用户ID格式错误
            throw new BizServiceException(F11607);
        }
        if (StringUtils.isEmpty(userName)) {
            //用户名不能为空
            throw new BizServiceException(F11608);
        }
        UserInfo userInfo = this.getUserInfo(userId);
        //用户不存在
        if (userInfo==null) {
            throw new BizServiceException(F11610);
        }
        userInfo.setUserName(userName);
        if (isAdmin!=null) {
            userInfo.setIsAdmin(isAdmin);
        }
        if (usable!=null) {
            userInfo.setUsable(usable);
        }
        userInfo.setUpdaterId(updaterId);
        userInfo.setUpdatedDate(new Date());

        managerRepository.update(userKeyPrefix + userId, userInfo);
    }

    /**
     * 修改用户密码
     */
    public void modifySecret(String userId, String newSecret, String reSecret, String updaterId) {
        if (!StringUtil.isSecret(newSecret)) {
            throw new BizServiceException(F11606);
        }
        if (!newSecret.equals(reSecret)) {
            throw new BizServiceException(F11619);
        }
        UserInfo userInfo = managerRepository.get(userKeyPrefix + userId, UserInfo.class);
        //用户不存在
        if (userInfo==null) {
            throw new BizServiceException(F11610);
        }
        userInfo.setSecret(BCrypt.hashpw(newSecret, BCrypt.gensalt()));
        userInfo.setUpdaterId(updaterId);
        userInfo.setUpdatedDate(new Date());

        managerRepository.update(userKeyPrefix + userId, userInfo);
    }

    /**
     * 修改我的密码
     */
    public void modifyMineSecret(String userId, String oldSecret, String newSecret, String reSecret) {
        UserInfo userInfo = managerRepository.get(userKeyPrefix + userId, UserInfo.class);
        //用户不存在或原密码错误
        if (userInfo==null || !BCrypt.checkpw(oldSecret, userInfo.getSecret())) {
            throw new BizServiceException(F11618);
        }
        this.modifySecret(userInfo.getUserId(), newSecret, reSecret, userInfo.getUserId());
    }

    /**
     * 获取用户信息
     */
    public UserInfo getUserInfo(String userId) {
        UserInfo userInfo = managerRepository.get(userKeyPrefix + userId, UserInfo.class);
        return userInfo;
    }

    /**
     * 获取用户信息列表
     */
    public List<UserInfo> getUserList() {
        List<UserInfo> userInfos = managerRepository.getList(userKeyPrefix, UserInfo.class);
        //抹除密码
        for (UserInfo userInfo: userInfos) {
            userInfo.setSecret(null);
        }
        return userInfos;
    }

    /**
     * 获取用户是否超管
     */
    public Boolean getUserIsAdmin(String userId) {
        UserInfo userInfo = managerRepository.get(userKeyPrefix + userId, UserInfo.class);
        return  userInfo!=null && userInfo.getUsable() && userInfo.getIsAdmin();
    }
}
